/**
 * @Description 产品分类相关操作
 * @method
 * @auth kely
 * @Date 2023-2-20
 * @Param
 * @return
 **/

package redis

import (
	"encoding/json"
	"github.com/edgexfoundry/edgex-go/internal/app/models"
	"github.com/edgexfoundry/go-mod-core-contracts/v2/common"
	"github.com/edgexfoundry/go-mod-core-contracts/v2/errors"

	"github.com/gomodule/redigo/redis"
)

const (
	ProductCategoryCollection      = "md|pc"
	ProductCategoryCollectionName  = ProductCategoryCollection + DBKeySeparator + common.Name
	ProductCategoryCollectionLabel = ProductCategoryCollection + DBKeySeparator + common.Label
)

// deviceStoredKey return the device's stored key which combines the collection name and object id
func productCategoryStoredKey(id string) string {
	return CreateKey(ProductCategoryCollection, id)
}

/**
 * @Description 获取产品分类列表查询
 * @method
 * @auth kely
 * @Date 2023-2-20
 * @Param
 * @return
 **/

// ProductCategorysByLabels query ProductCategorys with offset, limit and labels
func ProductCategorysByLabels(conn redis.Conn, offset int, limit int, labels []string) (ProductCategorys []models.ProductCategory, edgeXerr errors.EdgeX) {
	objects, edgeXerr := getObjectsByLabelsAndSomeRange(conn, ZREVRANGE, ProductCategoryCollection, labels, offset, limit)
	if edgeXerr != nil {
		return ProductCategorys, errors.NewCommonEdgeXWrapper(edgeXerr)
	}

	ProductCategorys = make([]models.ProductCategory, len(objects))
	for i, in := range objects {
		dp := models.ProductCategory{}
		err := json.Unmarshal(in, &dp)
		if err != nil {
			return []models.ProductCategory{}, errors.NewCommonEdgeX(errors.KindDatabaseError, "device format parsing failed from the database", err)
		}
		ProductCategorys[i] = dp
	}
	return ProductCategorys, nil
}

/**
 * @Description 获取产品分类列表模糊查询
 * @method
 * @auth kely
 * @Date 2023-2-23
 * @Param
 * @return
 **/

// ProductCategorysByLabels query ProductCategorys with offset, limit and labels
func ProductCategorysByName(conn redis.Conn, offset int, limit int, labels []string) (ProductCategorys []models.ProductCategory, edgeXerr errors.EdgeX) {
	objects, edgeXerr := getObjectsByLabelsAndSomeRange(conn, ZREVRANGE, ProductCategoryCollection, labels, offset, limit)
	if edgeXerr != nil {
		return ProductCategorys, errors.NewCommonEdgeXWrapper(edgeXerr)
	}

	ProductCategorys = make([]models.ProductCategory, len(objects))
	for i, in := range objects {
		dp := models.ProductCategory{}
		err := json.Unmarshal(in, &dp)
		if err != nil {
			return []models.ProductCategory{}, errors.NewCommonEdgeX(errors.KindDatabaseError, "device format parsing failed from the database", err)
		}
		ProductCategorys[i] = dp
	}
	return ProductCategorys, nil
}

/**
 * @Description
 * @method
 * @auth kely
 * @Date ${DATE}
 * @Param
 * @return
 **/

func sendAddProductCategoryCmd(conn redis.Conn, storedKey string, d models.ProductCategory) errors.EdgeX {
	dsJSONBytes, err := json.Marshal(d)
	if err != nil {
		return errors.NewCommonEdgeX(errors.KindContractInvalid, "unable to JSON marshal device for Redis persistence", err)
	}
	var mdpcNmae = ProductCategoryCollectionName + ":" + d.Name
	_ = conn.Send(SET, storedKey, dsJSONBytes)
	_ = conn.Send(SET, mdpcNmae, dsJSONBytes) // 添加name属性用来模糊查询
	_ = conn.Send(ZADD, ProductCategoryCollection, 0, storedKey)
	_ = conn.Send(HSET, ProductCategoryCollectionName, d.Name, storedKey)
	return nil
}

// productCategoryIdExists checks whether the productCategory exists by id
func productCategoryIdExists(conn redis.Conn, id string) (bool, errors.EdgeX) {
	exists, err := objectIdExists(conn, deviceStoredKey(id))
	if err != nil {
		return false, errors.NewCommonEdgeX(errors.KindDatabaseError, "device existence check by id failed", err)
	}
	return exists, nil
}

// deviceNameExists whether the device exists by name
func productCategoryNameExists(conn redis.Conn, name string) (bool, errors.EdgeX) {
	exists, err := objectNameExists(conn, ProductCategoryCollectionName, name)
	if err != nil {
		return false, errors.NewCommonEdgeX(errors.KindDatabaseError, "device existence check by name failed", err)
	}
	return exists, nil
}
